/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.huawei.radarviewlib;

import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.functions.Consumer;
import io.reactivex.rxjava3.openharmony.schedulers.OpenHarmonySchedulers;
import io.reactivex.rxjava3.schedulers.Schedulers;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.app.Context;

import java.security.SecureRandom;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * RadarCommpent
 *
 * @author jjy
 * @since 2021-04-23
 */
public class RadarCommpent extends DependentLayout implements Component.ClickedListener {
    private static final int DURING = 300;
    private final CompositeDisposable disposables = new CompositeDisposable();
    private Context mContext;
    private RadarView mRadarView;
    private Component top1Layout;
    private Component top2Layout;
    private RaderWheelView mRaderWheelView;
    private Button acclerateBtn;
    private DependentLayout checkLayoutAnimator;
    private Text wifiAcclerateTvTip;
    private Text mCheckTips;
    private DependentLayout checkLayoutAcclerate;
    private Image image3;
    private Image image2;
    private Image image1;
    private Text wifiAcclerateTvOptimzeCore;
    private DependentLayout checkdLayoutAnimator;
    private Text optimzeCore;
    private DependentLayout checkLayoutOptimize;
    private DependentLayout checkLayoutTop;
    private Text scoreTv;
    private AnimatorValue animator1;
    private AnimatorValue animator2;
    private AnimatorValue animator3;
    private int core;
    private int mChannelId;
    int progress = 100;
    private SecureRandom mRandom = new SecureRandom();
    private int topColor = 0xff15B96B;
    private int middColor = 0xffF29336;
    private int lowColor = 0xffEC6066;

    /**
     * 构造函数
     *
     * @param context context对象
     */
    public RadarCommpent(Context context) {
        super(context);
    }

    /**
     * 构造函数
     *
     * @param context context对象
     * @param attrSet 属性值
     */
    public RadarCommpent(Context context, AttrSet attrSet) {
        super(context, attrSet);
        topColor = attrSet.getAttr("topColor").get().getIntegerValue();
        middColor = attrSet.getAttr("middColor").get().getIntegerValue();
        lowColor = attrSet.getAttr("lowColor").get().getIntegerValue();
        this.mContext = context;
        initView();
    }

    private void initView() {
        Component layoutScatter = LayoutScatter.getInstance(mContext).parse(ResourceTable.Layout_radarview, this, true);
        mRadarView = (RadarView) layoutScatter.findComponentById(ResourceTable.Id_check_radar_view);
        top1Layout = (Component) layoutScatter.findComponentById(ResourceTable.Id_check_layout_top_1);
        top2Layout = (Component) layoutScatter.findComponentById(ResourceTable.Id_check_layout_top_2);
        mRaderWheelView = (RaderWheelView) layoutScatter.findComponentById(ResourceTable.Id_check_radar_wheel_view);
        acclerateBtn = (Button) layoutScatter.findComponentById(ResourceTable.Id_wifi_acclerate_btn);
        acclerateBtn.setTag(1);
        checkLayoutAnimator = (DependentLayout) layoutScatter.findComponentById(ResourceTable.Id_check_layout_animator);
        wifiAcclerateTvTip = (Text) layoutScatter.findComponentById(ResourceTable.Id_wifi_acclerate_tv_tip);
        mCheckTips = (Text) layoutScatter.findComponentById(ResourceTable.Id_wifi_acclerate_tv_check);
        checkLayoutAcclerate = (DependentLayout) layoutScatter.findComponentById(ResourceTable.Id_check_layout_acclerate);
        image3 = (Image) layoutScatter.findComponentById(ResourceTable.Id_image3);
        image2 = (Image) layoutScatter.findComponentById(ResourceTable.Id_image2);
        image1 = (Image) layoutScatter.findComponentById(ResourceTable.Id_image1);
        wifiAcclerateTvOptimzeCore = (Text) layoutScatter.findComponentById(ResourceTable.Id_wifi_acclerate_tv_optimze_core);
        checkdLayoutAnimator = (DependentLayout) layoutScatter.findComponentById(ResourceTable.Id_checkd_layout_animator);
        optimzeCore = (Text) layoutScatter.findComponentById(ResourceTable.Id_wifi_optimize_tv_tip);
        checkLayoutOptimize = (DependentLayout) layoutScatter.findComponentById(ResourceTable.Id_check_layout_optimize);
        checkLayoutTop = (DependentLayout) layoutScatter.findComponentById(ResourceTable.Id_check_layout_top);
        scoreTv = (Text) layoutScatter.findComponentById(ResourceTable.Id_check_tv_score);
        mRadarView.start();
        acclerateBtn.setClickedListener(this::onClick);
    }

    @Override
    public void onClick(Component component) {
        int Tag = Integer.parseInt(component.getTag().toString());
        switch (Tag) {
            case 1:
                checkLayoutAcclerate.setVisibility(Component.INVISIBLE);
                checkLayoutOptimize.setVisibility(Component.VISIBLE);
                showOptimzeAnimator(mChannelId);
                showOptimzeAnimator(mChannelId);
                break;
            default:
                break;
        }
    }

    private void stopAnimator() {
        animator1.setLoopedCount(0);
        animator1.setDuration(0);
        animator1.end();
        animator1.stop();
        animator3.setLoopedCount(0);
        animator3.setDuration(0);
        animator3.end();
        animator3.stop();
    }

    private void initAnimator() {
        animator1 = new AnimatorValue();
        animator1.setDuration(500);
        animator1.setCurveType(Animator.CurveType.LINEAR);
        animator1.setLoopedCount(AnimatorProperty.INFINITE);
        animator1.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                float value = (v * 360) + 90;
                image1.setRotation(value);
            }
        });
        animator1.start();
        animator2 = new AnimatorValue();
        animator2.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {

            }
        });
        animator3 = new AnimatorValue();
        animator3.setDuration(1000);
        animator3.setLoopedCount(AnimatorProperty.INFINITE);
        animator3.setCurveType(Animator.CurveType.LINEAR);
        animator3.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                float value = 360 * (1 - v);
                image3.setRotation(value);
            }
        });
        animator3.start();
    }

    public void showCheckProcess(int channelId) {
        this.mChannelId = channelId;
        int time = 0;
        switch (channelId) {
            case -1:
            case 0:
                core = 50;
                channelId = 11;
                break;
            case 1:
                core = 75;
                channelId = 15;
                break;
            case 2:
                core = 100;
                channelId = 20;
                break;
            case 3:
                core = 100;
                channelId = 20;
                break;
            case 11:
                core = 50;
                break;
            case 12:
                core = 60;
                break;
            case 13:
                core = 65;
                break;
            case 14:
                core = 70;
                break;
            case 15:
                core = 75;
                break;
            case 16:
                core = 80;
                break;
            case 17:
                core = 85;
                break;
            case 18:
                core = 90;
                break;
            case 19:
                core = 95;
                break;
            case 20:
                core = 100;
                break;
            default:
                core = 50;
                channelId = 11;
                break;
        }
        if (channelId < 4) {
            time = 34 - (4 - channelId);
        } else {
            time = 34 - (21 - channelId);
        }
        final int finalCore = core;
        final int finalTime = time;
        rxOpenHarmonyTestCase1(DURING, finalCore, finalTime);
    }
    public void rxOpenHarmonyTestCase1(int during, int finalCore, int finalTime) {
        disposables.add(sampleObservable(during)
                .subscribeOn(Schedulers.io())
                .observeOn(OpenHarmonySchedulers.mainThread()).take(34).subscribe(new Consumer<Long>() {
                    @Override
                    public void accept(Long longTime) throws Throwable {
                        int id = longTime.intValue();
                        if (id >= finalTime) {
                            if (progress > finalCore) {
                                if (progress > 60) {
                                    progress = progress - (mRandom.nextInt(5) + 1);
                                    showBackground(progress);
                                    scoreTv.setText(String.valueOf(progress));
                                    progress = (progress + 5) / 5 * 5 - 5;
                                } else {
                                    progress = progress - (mRandom.nextInt(10) + 1);

                                    showBackground(progress);
                                    scoreTv.setText(String.valueOf(progress));
                                    progress = progress / 10 * 10;
                                }

                            } else {
                                if (core <= 70) {
                                    showBackground(50);
                                } else if (core > 70 && core <= 90) {
                                    showBackground(75);
                                } else {
                                    showBackground(100);
                                }
                                mRadarView.stop();
                                mRadarView.setStopRoate(true);
                                mRaderWheelView.stop();
                                scoreTv.setText(String.valueOf(finalCore));
                                mRadarView.setCodeangel(finalCore * 360 / 100);
                                mCheckTips.setVisibility(Component.INVISIBLE);
                                if (finalCore != 100) {
                                    mRadarView.start();
                                    acclerateBtn.setVisibility(Component.VISIBLE);
                                } else {
                                    mRadarView.stop();
                                }
                            }
                        }
                    }
                }, throwable -> {
                }));
    }

    public void showBackground(int core) {
        System.out.println("showBackgroundcore : " + core);
        if (core > 90 && core <= 100) {
            top1Layout.setAlpha(1);
            top2Layout.setAlpha(1);
            ShapeElement element = new ShapeElement();
            element.setRgbColor(RgbColor.fromRgbaInt(ResourceTable.Color_wifi_acclerate_green));
            top2Layout.setBackground(element);
            element.setRgbColor(RgbColor.fromArgbInt(topColor));
            top1Layout.setBackground(element);
        } else if (core >= 75 && core <= 90) {
            float topAlpha = (float) ((core - 75) * 0.04);
            top2Layout.setAlpha(topAlpha);
            top1Layout.setAlpha(1 - topAlpha);
            ShapeElement element = new ShapeElement();
            element.setRgbColor(RgbColor.fromArgbInt(middColor));
            top1Layout.setBackground(element);
        } else {
            float topAlpha = (float) ((core - 50) * 0.04);
            top2Layout.setAlpha(topAlpha);
            top1Layout.setAlpha(1 - topAlpha);
            ShapeElement element = new ShapeElement();
            element.setRgbColor(RgbColor.fromArgbInt(middColor));
            top2Layout.setBackground(element);
            element.setRgbColor(RgbColor.fromArgbInt(lowColor));
            top1Layout.setBackground(element);
        }
    }

    static Observable<Long> sampleObservable(int during) {
        return Observable.interval(during, TimeUnit.MILLISECONDS);
    }

    static Observable<Long> longObservable() {
        return Observable.interval(500, 500, TimeUnit.MILLISECONDS);
    }

    public void showOptimzeAnimator(int channelId) {
        /**
         * 初始化优化的动画
         */
        initAnimator();
        optimzeCore.setText(String.valueOf(core));
        /**
         * 这里是优化以后的自动加分
         */
        progress = core;
        disposables.add(longObservable()
                .subscribeOn(Schedulers.io())
                .observeOn(OpenHarmonySchedulers.mainThread())
                .take(20 - channelId + 1)
                .subscribe(aLong -> {
                    if (progress < 100) {
                        if (progress == 50) {
                            int score = progress + mRandom.nextInt(10) + 1;
                            showBackground(score);
                            wifiAcclerateTvOptimzeCore.setText(String.valueOf(score));
                            progress = progress + 10;
                        } else if (progress >= 60 && progress < 100) {
                            int score = progress + mRandom.nextInt(5) + 1;
                            showBackground(score);
                            wifiAcclerateTvOptimzeCore.setText(String.valueOf(score));
                            progress = progress + 5;
                        } else {
                            showBackground(99);
                            wifiAcclerateTvOptimzeCore.setText(String.valueOf(99));
                            progress = progress + 5;
                        }
                    } else {
                        showBackground(100);
                        wifiAcclerateTvOptimzeCore.setText(String.valueOf(100));
                        stopAnimator();
                        image1.setVisibility(Component.INVISIBLE);
                        image3.setVisibility(Component.INVISIBLE);
                    }
                }, throwable -> {
                     System.out.println("throwablecore" + throwable.getMessage());
                }));
    }
}
